//
//  DigitalMessage.m
//  GJDigitalSDK
//
//  Created by 吴棒棒 on 2021/10/30.
//

#import "DigitalMessage.h"
#import "XMPPManager/XMPPManager.h"
#import "DigitalConfig.h"
#import "RTCSessionDescription+JSON.h"
#import "OpenUDID-master/OpenUDID.h"

static NSString * const kARDMediaStreamId = @"ARDAMS";
static NSString * const kARDAudioTrackId = @"ARDAMSa0";
static NSString * const kARDVideoTrackId = @"ARDAMSv0";
@interface DigitalMessage ()<RTCPeerConnectionDelegate, XMPPManagerDelegate, RTCDataChannelDelegate>

@end
@implementation DigitalMessage

static DigitalMessage *manager = nil;

+ (DigitalMessage *)shareMessage
{
    static dispatch_once_t oneToken;
    dispatch_once(&oneToken, ^{
        manager = [[DigitalMessage alloc]init];
    });
    return manager;
}

- (void)initDigital {
    // 外音
    RTCAudioSessionConfiguration *webRTCConfig =
    [RTCAudioSessionConfiguration webRTCConfiguration];
    webRTCConfig.categoryOptions = webRTCConfig.categoryOptions |
    AVAudioSessionCategoryOptionDefaultToSpeaker;

    webRTCConfig.sampleRate=kRTCAudioSessionLowComplexitySampleRate;

    [RTCAudioSessionConfiguration setWebRTCConfiguration:webRTCConfig];
    
    /// 初始化工厂，一定要编码解码
    RTCDefaultVideoEncoderFactory * encoderFactory = [[RTCDefaultVideoEncoderFactory alloc] init];
    RTCDefaultVideoDecoderFactory*  decoderFactory = [[RTCDefaultVideoDecoderFactory alloc] init];
    self.factory= [[RTCPeerConnectionFactory alloc] initWithEncoderFactory:encoderFactory
                                                  decoderFactory:decoderFactory];
    
    /// 创建本地音视频流
    [self createLocalStream];
    
    /// 创建PeerConnection
    [self createPublisherPeerConnection];

    
}
- (void)createLocalStream {
    
    //如果为空，则创建点对点工厂
    
    NSArray<AVCaptureDevice *> *captureDevices = [RTCCameraVideoCapturer captureDevices];
    AVCaptureDevicePosition position = [DigitalConfig shareConfig].usingFrontCamera ? AVCaptureDevicePositionFront : AVCaptureDevicePositionBack;
    AVCaptureDevice * device = captureDevices[0];
    for (AVCaptureDevice *obj in captureDevices)
    {
        if (obj.position == position)
        {
            device = obj;
            break;
        }
    }
    //检测摄像头权限
    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    if(authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied)
    {
        NSLog(@"相机访问受限");
    }
    else
    {
        if (device)
        {
            //创建本地流
//            _localStream = [_factory mediaStreamWithStreamId:@"ARDAMS"];
            
            
            //获取数据源
            RTCVideoSource *_source = [_factory videoSource];

            RTCMediaConstraints *constraints = [self defaultMediaAudioConstraints];
            RTCAudioSource *source = [_factory audioSourceWithConstraints:constraints];
            RTCAudioTrack *track = [_factory audioTrackWithSource:source trackId:kARDAudioTrackId];
//            RTCAudioTrack * track = [_factory audioTrackWithTrackId:kARDAudioTrackId];
            self.localAudioTrack = track;

            //视频

            self.videoCapturer = [[RTCCameraVideoCapturer alloc] initWithDelegate:_source];
            RTCVideoTrack *videoTrack=[self.factory videoTrackWithSource:_source trackId:kARDMediaStreamId];
            self.localTrack = videoTrack;

            
            //拿到capture对象
            RTCCameraVideoCapturer * capture = [[RTCCameraVideoCapturer alloc] initWithDelegate:_source];
            AVCaptureDeviceFormat * format = [[RTCCameraVideoCapturer supportedFormatsForDevice:device] lastObject];
            CGFloat fps = [[format videoSupportedFrameRateRanges] firstObject].maxFrameRate;
            
            [capture startCaptureWithDevice:device format:format fps:fps completionHandler:^(NSError * error) {
                NSLog(@"startCaptureWithDevice---：%@",error);
                
                dispatch_async(dispatch_get_main_queue(), ^{
                    if ([DigitalConfig shareConfig].isShowLocalVideo) {
                        //展示预览
                        if (self.delegate&&[self.delegate respondsToSelector:@selector(setCaptureSession:)]) {
                            [self.delegate setCaptureSession:[capture captureSession]];
                        }
                    }
                });
            }];
        }
        else
        {
            NSLog(@"该设备不能打开摄像头");
        }
    }
    //    }
}

- (void)createPublisherPeerConnection {
    self.publisherPeerConnection = [self createPeerConnection];
    if ([DigitalConfig shareConfig].isShowLocalAudio) {
        [self createAudioSender:self.publisherPeerConnection];
    }
    
    if ([DigitalConfig shareConfig].isShowLocalVideo) {
        [self createVideoSender:self.publisherPeerConnection];
    }

}

- (RTCMediaConstraints *)defaultPeerConnectionConstraints {
    NSDictionary *optionalConstraints = @{ @"DtlsSrtpKeyAgreement" : @"true" };
    RTCMediaConstraints* constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:nil  optionalConstraints:optionalConstraints];
    return constraints;
}

- (RTCIceServer *)defaultSTUNServer {
    NSArray *array = [NSArray arrayWithArray:[DigitalConfig shareConfig].stunList];
    RTCIceServer *iceServer = [[RTCIceServer alloc] initWithURLStrings:array
                                                              username:@""
                                                            credential:@"" tlsCertPolicy:RTCTlsCertPolicyInsecureNoCheck];
    return iceServer;
}

- (RTCPeerConnection *)createPeerConnection {
    RTCMediaConstraints *constraints = [self defaultPeerConnectionConstraints];
    RTCConfiguration *config = [[RTCConfiguration alloc] init];
    NSMutableArray *iceServers = [NSMutableArray arrayWithObject:[self defaultSTUNServer]];
    config.iceServers = iceServers;
    config.iceTransportPolicy = RTCIceTransportPolicyAll;
    RTCPeerConnection *peerConnection = [_factory peerConnectionWithConfiguration:config
                                         constraints:constraints
                                            delegate:self];
    return peerConnection;
}


- (void)createDataChannelWithPeerConnection:(RTCPeerConnection*)peerConnection connectionId:(NSString*)connectionId{
    //给p2p连接创建dataChannel
    RTCDataChannelConfiguration *dataChannelConfiguration = [[RTCDataChannelConfiguration alloc] init];
    dataChannelConfiguration.isNegotiated = NO;
    self.localDataChannel = [peerConnection dataChannelForLabel:@"localDataChannel" configuration:dataChannelConfiguration];
     self.localDataChannel.delegate = self;
}
- (RTCMediaConstraints *)creatConstraintWithOption {
    RTCMediaConstraints *constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:@{kRTCMediaConstraintsOfferToReceiveAudio:kRTCMediaConstraintsValueTrue,kRTCMediaConstraintsOfferToReceiveVideo:kRTCMediaConstraintsValueTrue} optionalConstraints:nil];
    return constraints;
}
- (RTCMediaConstraints *)defaultMediaAudioConstraints {
    
    NSDictionary *mandatoryConstraints = @{@"noiseSuppression": @"true",@"echoCancellation": @"true"};
    RTCMediaConstraints *constraints =
    [[RTCMediaConstraints alloc] initWithMandatoryConstraints:mandatoryConstraints
                                          optionalConstraints:nil];
    return constraints;
}


- (RTCMediaConstraints *)defaultOfferConstraints {
    NSDictionary *mandatoryConstraints = @{
                                           @"OfferToReceiveAudio" : @"true",
                                           @"OfferToReceiveVideo" : @"true"
                                           };
    RTCMediaConstraints* constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:mandatoryConstraints optionalConstraints:nil];
    return constraints;
}

- (RTCAudioTrack *)createLocalAudioTrack {

    RTCMediaConstraints *constraints = [self defaultMediaAudioConstraints];
    RTCAudioSource *source = [_factory audioSourceWithConstraints:constraints];
    RTCAudioTrack *track = [_factory audioTrackWithSource:source trackId:kARDAudioTrackId];

    return track;
}

- (RTCRtpSender *)createAudioSender:(RTCPeerConnection *)peerConnection {
    RTCRtpSender *sender = [peerConnection senderWithKind:kRTCMediaStreamTrackKindAudio streamId:kARDMediaStreamId];
    if (self.localAudioTrack) {
        sender.track = self.localAudioTrack;
    }
    return sender;
}


- (RTCVideoTrack *)createLocalVideoTrack
{
    RTCVideoSource *videoSource=self.factory.videoSource;


    self.videoCapturer = [[RTCCameraVideoCapturer alloc] initWithDelegate:videoSource];
    RTCVideoTrack *videoTrack=[self.factory videoTrackWithSource:videoSource trackId:kARDVideoTrackId];
    
    return videoTrack;


}
- (RTCRtpSender *)createVideoSender:(RTCPeerConnection *)peerConnection {
    RTCRtpSender *sender = [peerConnection senderWithKind:kRTCMediaStreamTrackKindVideo
                                                 streamId:kARDMediaStreamId];
    if (self.localTrack) {
        sender.track = self.localTrack;
    }

    return sender;
}

#pragma mark - RTCPeerConnectionDelegate

- (void)peerConnection:(RTCPeerConnection *)peerConnection didAddStream:(RTCMediaStream *)stream {

    dispatch_async(dispatch_get_main_queue(), ^{
        if (stream.videoTracks.count) {

            if(self.delegate && [self.delegate respondsToSelector:@selector(didAddStream:)]) {
                [self.delegate didAddStream:stream];
            }
  
        }
    });
}

- (void)peerConnection:(RTCPeerConnection *)peerConnection didRemoveStream:(RTCMediaStream *)stream {
    NSLog(@"=========didRemoveStream");
}

- (void)peerConnection:(RTCPeerConnection *)peerConnection didOpenDataChannel:(RTCDataChannel *)dataChannel {

}

- (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeSignalingState:(RTCSignalingState)stateChanged {
    NSLog(@"stateChanged === %ld", (long)stateChanged);
}

- (void)peerConnection:(RTCPeerConnection *)peerConnection didGenerateIceCandidate:(RTCIceCandidate *)candidate {

    NSLog(@"=========didGenerateIceCandidate==%@", candidate.sdp);
    
    if(candidate) {
        if (self.delegate && [self.delegate respondsToSelector:@selector(didGenerateIceCandidate:)]) {
            [self.delegate didGenerateIceCandidate:candidate];
        }
    }else {
        
    }

}

- (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeIceGatheringState:(RTCIceGatheringState)newState
{
    NSLog(@"RTCIceGatheringState === %ld", (long)newState);
}

- (void)peerConnectionShouldNegotiate:(RTCPeerConnection *)peerConnection {

}

- (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeIceConnectionState:(RTCIceConnectionState)newState {
    NSLog(@"RTCIceGatheringState === %ld", (long)newState);
    if (self.delegate && [self.delegate respondsToSelector:@selector(didIceConnectionChange:)]) {
        [self.delegate didIceConnectionChange:newState];
    }
}

- (void)peerConnection:(RTCPeerConnection *)peerConnection didRemoveIceCandidates:(NSArray<RTCIceCandidate *> *)candidates {
    NSLog(@"=========didRemoveIceCandidates");
}

#pragma mark - RTCDataChannelDelegate
/** The data channel state changed. */
- (void)dataChannelDidChangeState:(RTCDataChannel *)dataChannel {
    
}

/** The data channel successfully received a data buffer. */
- (void)dataChannel:(RTCDataChannel *)dataChannel
didReceiveMessageWithBuffer:(RTCDataBuffer *)buffer {
    
}
/// 设置remote
- (void)onPublisherRemoteJsep:(NSNumber *)handleId dict:(NSDictionary *)jsep {
    __weak typeof(self) weakSelf = self;
    RTCSessionDescription *answerDescription = [RTCSessionDescription descriptionFromJSONDictionary:jsep];
    [self.publisherPeerConnection setRemoteDescription:answerDescription completionHandler:^(NSError * _Nullable error) {
        __strong typeof(self) strongSelf = weakSelf;//ARC
        if (error!=nil) {
            if(strongSelf.delegate && [strongSelf.delegate respondsToSelector:@selector(onError:)]) {
                [strongSelf.delegate onError:error];
            }
            return;
        }
        [strongSelf offerPeerConnection:handleId];

    }];
}
- (void)offerPeerConnection: (NSNumber*) handleId {
    //    [self createDataChannelWithPeerConnection:publisherPeerConnection connectionId:[NSString stringWithFormat:@"%@",handleId]];
    
    __weak typeof(self) weakSelf = self;

    [self.publisherPeerConnection answerForConstraints:[self defaultOfferConstraints]
                                     completionHandler:^(RTCSessionDescription *sdp,
                                                         NSError *error) {
        __strong typeof(self) strongSelf = weakSelf;

        if (error!=nil) {
            if(strongSelf.delegate && [strongSelf.delegate respondsToSelector:@selector(onError:)]) {
                [strongSelf.delegate onError:error];
            }
            return;
        }
        
        if(strongSelf.delegate && [strongSelf.delegate respondsToSelector:@selector(sendXmppForSdp:)]) {
            [strongSelf.delegate sendXmppForSdp:sdp];
        }
        
        [self.publisherPeerConnection setLocalDescription:sdp completionHandler:^(NSError * _Nullable error) {
            if (error!=nil) {
                if(strongSelf.delegate && [strongSelf.delegate respondsToSelector:@selector(onError:)]) {
                    [strongSelf.delegate onError:error];
                }
                return;
            }
        }];
    }];
}
- (void)addCandidate:(NSDictionary *)dic {
    RTCIceCandidate *candidate = [[RTCIceCandidate alloc] initWithSdp:dic[@"candidate"] sdpMLineIndex:[dic[@"sdpMLineIndex"] intValue] sdpMid:dic[@"sdpMid"]];
    [self.publisherPeerConnection addIceCandidate:candidate];
}

@end
